package com.jyxd.web.mq;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jyxd.web.data.basic.NursingTask;
import com.jyxd.web.data.dto.NursingTaskDTO;
import com.jyxd.web.data.patient.Patient;
import com.jyxd.web.service.assessment.basic.NursingTaskService;
import com.jyxd.web.service.patient.PatientService;
import com.rabbitmq.client.Channel;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class NursingTaskReceiver {
    private final Logger logger = LoggerFactory.getLogger(NursingTaskReceiver.class);

    private final NursingTaskExecuteSender nursingTaskExecuteSender;

    private final NursingTaskSender nursingTaskSender;
    private final NursingTaskService nursingTaskService;

    private final PatientService patientService;

    public NursingTaskReceiver(NursingTaskExecuteSender nursingTaskExecuteSender, NursingTaskService nursingTaskService, NursingTaskSender nursingTaskSender, PatientService patientService) {
        this.nursingTaskExecuteSender = nursingTaskExecuteSender;
        this.nursingTaskService = nursingTaskService;
        this.nursingTaskSender = nursingTaskSender;
        this.patientService = patientService;
    }

    @Value("${icu.job.mq.nurse.delay.queue}")
    private String nursingTaskQueue;

    @RabbitListener(queuesToDeclare = {@Queue("#{nursingTaskQueue}")})
    public void process(Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag, @Payload NursingTask nursingTask) throws IOException {

        logger.info("本轮执行时间:{},执行数据插入时间:{}", DateUtil.formatDateTime(new Date()), DateUtil.formatDateTime(nursingTask.getNextExecuteTime()));
        logger.info(nursingTask.toString());
        try {
            NursingTask databaseNursingTask;
            QueryWrapper<NursingTask> queryWrapper = new QueryWrapper<>();

            databaseNursingTask = nursingTaskService.getOne(queryWrapper.eq("id", nursingTask.getId()));

            //如果病人已经出科，停止
            Map<String, Object> query = new HashMap<>();
            query.put("id", nursingTask.getPatientId());
            Patient patient = patientService.getPatientByConditions(query);
            if (patient.getStatus() == 2 && patient.getFlag() != 1) {
                if (ObjectUtils.isNotEmpty(patient.getExitTime())) {
                    databaseNursingTask.setDiscardTime(patient.getExitTime());
                } else if (ObjectUtils.isNotEmpty(patient.getDeathTime())) {
                    databaseNursingTask.setDiscardTime(patient.getDeathTime());
                } else {
                    databaseNursingTask.setDiscardTime(new Date());
                }
                databaseNursingTask.setDiscardReason("患者已出科(" + patient.getExitType() + ")");
                databaseNursingTask.setStatus(-1);
                nursingTaskService.updateById(databaseNursingTask);
            }

            if (databaseNursingTask.getStatus() == -1) {
                logger.info("NursingTask({}) 已经停止执行", nursingTask.getId());
                //如果任务时间 < 停止时间需要补充数据
                long nextTimestamp = nursingTask.getNextExecuteTime().getTime();
                if (databaseNursingTask.getDiscardTime() != null && databaseNursingTask.getDiscardTime().getTime() > nextTimestamp) {
                    nursingTaskService.repairNursingTask(patient, nursingTask, nursingTask.getNextExecuteTime(), databaseNursingTask.getDiscardTime());
                }
                return;
            }

            //添加本次记录
            NursingTaskDTO nursingTaskDTO = BeanUtil.copyProperties(nursingTask, NursingTaskDTO.class);
            nursingTaskDTO.setDataTime(nursingTask.getNextExecuteTime());
            nursingTaskExecuteSender.send(nursingTaskDTO);

            //发送下次计划任务,
            Date nextExecuteDateTime = new Date(nursingTask.getNextExecuteTime().getTime() + nursingTask.getFrequencyDuration());
            Date now = new Date();
            long nextExecuteTimestamp = nextExecuteDateTime.getTime();
            //如果下次时间小于当前时间,执行补录
            if (nextExecuteTimestamp < now.getTime()) {
                nextExecuteTimestamp = nursingTaskService.repairNursingTask(patient, nursingTask, nextExecuteDateTime, new Date());
                nextExecuteDateTime = new Date(nextExecuteTimestamp);
            }

            nursingTask.setNextExecuteTime(nextExecuteDateTime);
            logger.info("NursingTask({}) 下次执行时间:{}", nursingTask.getId(), DateUtil.formatDateTime(nextExecuteDateTime));
            long duration = nextExecuteDateTime.getTime() - new Date().getTime();
            nursingTaskSender.send(nursingTask, duration);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("NursingTaskReceiver process error:{}", e.getMessage());
        } finally {
            channel.basicAck(tag, false);
        }
    }

    @Bean(name = "nursingTaskQueue")
    public String getNursingTaskQueue() {
        return nursingTaskQueue;
    }
}
